package moodish.server;

import java.util.ArrayList;
import moodish.comm.ServerComm;
import moodish.comm.ServerSideMessage;

public class servertest implements MoodishServer{

    private ArrayList<String> clienteligado = new ArrayList<String>();
    private ArrayList<String> clienteparadesligar = new ArrayList<String>();
    private ArrayList<String> amigo = new ArrayList<String>();

    // STANDARD ERROR MESSAGES
    public static final String ERROR_CLIENT_OFFLINE = "ERROR - Client offline";
    public static final String ERROR_FRIEND_D_OFFLINE = "ERROR - Friend(d) offline";
    public static final String ERROR_PAYLOAD_NULL = "ERROR - Payload is null";
    public static final String ERROR_SERVERCOMM_NULL = "ERROR - serverComm is null";
   
    public static final String ERROR_MESSAGE_NULL = "ERROR - serverComm.getNextMessage() returns null";
    public static final String ERROR_DUPLICATED_NICKNAME = "";

    private ArrayList<String> errorLog = new ArrayList<String>();
    private int numberOfErrors = 0;
	
	private ServerComm ser;
	@Override
	public void start(ServerComm serverComm) {
		this.ser = serverComm;
		while(true)
		{
			ser.start();
			recebermsg();
		}
		
	}
	private void recebermsg() {
		
		while (true)
		{
			if (ser.hasNextMessage())
			{
				ServerSideMessage msg = ser.getNextMessage();
				switch (msg.getType()) {
				case CLIENT_CONNECTED:
					processClientConnectedMessage(msg);
				break;
					
				case CLIENT_DISCONNECTED:
					 try
					 {
                         processClientDisconnectedMessage(msg);
                
	                 } catch (IllegalArgumentException ex){
	                         if(ex.getMessage().equals(ERROR_CLIENT_OFFLINE)){
	                                 errorLog.add(ERROR_CLIENT_OFFLINE);
	                                 numberOfErrors++;
	                         }
	                 }

				break;
					
				case FRIENDSHIP:
					 try
					 {
                         addfriend(msg);
	                 } 
					 catch (IllegalArgumentException ex)
					 {
	                         if(ex.getMessage().equals(ERROR_CLIENT_OFFLINE)){
	                                 System.out.println(ERROR_CLIENT_OFFLINE);
	                         } else {
	                                 if(ex.getMessage().equals(ERROR_PAYLOAD_NULL)){
	                                         ser.sendError(msg.getClientNickname(), ERROR_PAYLOAD_NULL);
	                                 } else {
	                                         if(ex.getMessage().equals(ERROR_FRIEND_D_OFFLINE)){
	                                                 ser.sendError(msg.getClientNickname(), ERROR_FRIEND_D_OFFLINE);
	                                         }
	                                 }
	                         }
	                         errorLog.add(ex.getMessage());
	                         numberOfErrors++;
	                 }

				break;
						
				case UNFREINDSHIP:
					try
					{
                        removefriend(msg);
					}
					catch (IllegalArgumentException ex)
					{
                        if(ex.getMessage().equals(ERROR_CLIENT_OFFLINE)){
                                /* The Network communications service
                                 * shouldn't allow to send a message without a sender.
                                 * But the service shouldn't go down because of it
                                 */
                                System.out.println(ERROR_CLIENT_OFFLINE);
                        } else {
                                if(ex.getMessage().equals(ERROR_PAYLOAD_NULL)){
                                        ser.sendError(msg.getClientNickname(), ERROR_PAYLOAD_NULL);
                                } else {
                                        if(ex.getMessage().equals(ERROR_FRIEND_D_OFFLINE)){
                                                ser.sendError(msg.getClientNickname(), ERROR_FRIEND_D_OFFLINE);
                                        }
                                }
                        }
                        errorLog.add(ex.getMessage());
                        numberOfErrors++;
					}

				break;
					
				case MOODISH_MESSAGE:
					try{
                        processmoodishMessage(msg);
               
					} catch (IllegalArgumentException ex){
                        if(ex.getMessage().equals(ERROR_CLIENT_OFFLINE)){
                                System.out.println(ERROR_CLIENT_OFFLINE);
                        } else {
                                if(ex.getMessage().equals(ERROR_PAYLOAD_NULL)){
                                        ser.sendError(msg.getClientNickname(), ERROR_PAYLOAD_NULL);
                                }
                        }
                        errorLog.add(ex.getMessage());
                        numberOfErrors++;
					}

				break;

				default:
					
				break;
				}
			}
		}
		
	}
	
	private void processmoodishMessage(ServerSideMessage msg) throws IllegalArgumentException
	{
		assert msg.getType() == ServerSideMessage.Type.MOODISH_MESSAGE;
        String nickname = msg.getClientNickname();
        String moodishMessage = msg.getPayload();
        String sender, reciver = null;
        // Check if moodishMessade has content
        if(moodishMessage != null){
                // Get the client
	        	int nclientedeligar = clienteligado.indexOf(nickname);
	        	sender = clienteligado.get(nclientedeligar);

                // Checking if client is online

                if(sender != null){
                        // Send the message to all the friends online.

                        for(int i =0; i < clienteligado.size(); i++){
                        	if(amigo.contains(sender.concat("-"+clienteligado.get(i))))
                                ser.sendMoodishMessage(nickname, clienteligado.get(i), moodishMessage);
                        }
                }
                else {
                        throw new IllegalArgumentException(ERROR_CLIENT_OFFLINE);
                }
        }
        else{
                throw new IllegalArgumentException(ERROR_PAYLOAD_NULL);
        }
	}

	private boolean getClientByNickname(String nickname)
	{            
        
        if(clienteligado.contains(nickname))
       	{
        	if(!clienteparadesligar.contains(nickname))
        		clienteparadesligar.add(nickname);
        	return false;
       	}
        //clienteligado.add(nickname);
        return true;
        
	}

	private void processClientConnectedMessage(ServerSideMessage msg){
		assert msg.getType() == ServerSideMessage.Type.CLIENT_CONNECTED;
        String nome = msg.getClientNickname();

        boolean nicknameIsAvailable = getClientByNickname(nome);

        // Checking if the choosen nickname is available, that is, if it isn't already being used
        if(nicknameIsAvailable)
        {   

                for(int i = 0; i < clienteligado.size(); i++)
                {
                	if(!clienteligado.equals(nome)){
                        ser.sendClientConnected(clienteligado.get(i), nome);
                        ser.sendClientConnected(nome, clienteligado.get(i));
                	}
                }
               
                // Add the client to the online clients list
                clienteligado.add(nome);

        }
        else 
        {
                ser.sendError(nome, ERROR_DUPLICATED_NICKNAME);
        }
	}

	private void processClientDisconnectedMessage(ServerSideMessage msg) throws IllegalArgumentException
	{
        assert msg.getType() == ServerSideMessage.Type.CLIENT_DISCONNECTED;
        String nickname = msg.getClientNickname();

        boolean clientGoing = getClientByNickname(nickname);
        int nclientedeligar = clienteparadesligar.indexOf(nickname);
        String colocardesligado = clienteparadesligar.get(nclientedeligar);
        //Checking if client is online
        if(clientGoing){
                //Delete client from the online client list
                clienteparadesligar.remove(nclientedeligar);
                clienteligado.remove(colocardesligado);
               
                //Warn the all the users about the disconnection
                for(int i = 0; i < clienteligado.size(); i++)
                {
                        String clientNickname = clienteligado.get(i);
                        ser.sendClientDisconnected(clientNickname, colocardesligado);
                }
               
               
        }
        else {
                throw new IllegalArgumentException(ERROR_CLIENT_OFFLINE);
        }
	}

	private void addfriend(ServerSideMessage message) throws IllegalArgumentException{

        if(message.getPayload() != null){
                String askerNickname = message.getClientNickname();
                String friendNickname = message.getPayload();
                String convidaramigo, asker = null;
                
                int nclientedeligar = clienteligado.indexOf(askerNickname);
                asker = clienteligado.get(nclientedeligar);

                // Checking if asker is online
                if(asker != null){
                        nclientedeligar = clienteligado.indexOf(friendNickname);
                        convidaramigo = clienteligado.get(nclientedeligar);
                        if(convidaramigo != null){
                                amigo.add(asker+"-"+convidaramigo);
                                amigo.add(convidaramigo+"-"+asker);

                                //Warn the followed about what happened;

                                ser.sendNewFriendship(asker, convidaramigo);
                        }
                        else{
                                throw new IllegalArgumentException(ERROR_FRIEND_D_OFFLINE);
                        }
                } else {
                        throw new IllegalArgumentException(ERROR_CLIENT_OFFLINE);
                }
        } else {
                throw new IllegalArgumentException(ERROR_PAYLOAD_NULL);
        }
	}

	 private void removefriend(ServerSideMessage message) throws IllegalArgumentException{

         // The client is asking to unfrinend the user on the payload
         String askerNickname = message.getClientNickname();
         String friendNickname = message.getPayload();
         String convidaramigo, asker = null;
         
         // Checking if payload has text
         if(message.getPayload() != null){
	        	 int nclientedeligar = clienteligado.indexOf(askerNickname);
	             asker = clienteligado.get(nclientedeligar);
                 //      Checking if the asker is online - Precondition
                 if(asker != null){
	                	 nclientedeligar = clienteligado.indexOf(friendNickname);
	                     convidaramigo = clienteligado.get(nclientedeligar);
                         // Checking if the choosen client friend is online
                         if(convidaramigo != null){
                                 if(amigo.contains(asker+"-"+convidaramigo))
                                 {
                                	 amigo.remove(asker+"-"+convidaramigo);
                                	 amigo.remove(convidaramigo+"-"+asker);
                                 }

                                 // Warn the followed client about what happened;

                                 ser.sendNewUnfriendship(friendNickname, askerNickname);
                         }
                         else {
                                 throw new IllegalArgumentException(ERROR_FRIEND_D_OFFLINE);
                         }
                 }
                 else {
                         throw new IllegalArgumentException(ERROR_CLIENT_OFFLINE);
                 }
         }
         else {
                 throw new IllegalArgumentException(ERROR_PAYLOAD_NULL);
         }
	 }

	
}
